package com.dalonedrau.jogl.opengl.ui.panel;

import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import com.dalonedrau.jogl.engine.GlobalConsts;
import com.dalonedrau.jogl.opengl.ui.GuiComponent;
import com.dalonedrau.jogl.opengl.ui.GuiSelectable;
import com.dalonedrau.jogl.opengl.ui.menu.MenuGroup;

/**
 * Panel implementation that displays only one child at a time.
 * @author Donald
 */
public class CardPanel extends Panel {
	/** the list of child components. */
	private HashMap<String, GuiComponent>	children;
	/** the {@link GuiComponent}'s preferred size. */
	private Dimension						preferredSize;
	/**
	 * Creates a new instance of {@link CardPanel}.
	 */
	public CardPanel() {
		preferredSize = new Dimension(0, 0);
		children = new HashMap<String, GuiComponent>();
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final void addChild(final GuiComponent child) {
		addChild(Integer.toString(child.getId()), child);
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final void addChild(final String name, final GuiComponent child) {
		children.put(name, child);
		child.setVisible(false);
		// re-size the panel
		preferredSize.width = 0;
		preferredSize.height = 0;
		getPreferredSize();
		// re-position the children
		if (super.getPosition() != null) {
			setPosition(
					super.getPosition().getX(),
					super.getPosition().getY(),
					super.getPosition().getZ());
		}
	}
	/**
	 * {@inheritDoc}
	 */
	public final void animate() {
		// TODO Auto-generated method stub

	}
	/** Clears the display. */
	public final void clearDisplay() {
		Iterator<String> iter = children.keySet().iterator();
		while (iter.hasNext()) {
			children.get(iter.next()).setVisible(false);
		}
	}
	/**
	 * Displays a specific child.
	 * @param name the name of the child
	 */
	public final void displayChild(final String name) {
		clearDisplay();
		children.get(name).setVisible(true);
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final GuiComponent[] getChildren() {
		Iterator<String> iter = children.keySet().iterator();
		ArrayList<GuiComponent> list = new ArrayList<GuiComponent>();
		while (iter.hasNext()) {
			list.add(children.get(iter.next()));
		}
		iter = null;
		return list.toArray(new GuiComponent[list.size()]);
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final Dimension getPreferredSize() {
		if (preferredSize.width == 0
				|| preferredSize.height == 0) {
			int w = 0, h = 0;
			if (getBorder() != null) {
				w = getBorder().getInsets().left;
				w += getBorder().getInsets().right;
				h = getBorder().getInsets().top;
				h += getBorder().getInsets().bottom;
			}
			w += getInsets().left + getInsets().right;
			h += getInsets().top + getInsets().bottom;
			int maxChildW = 0, maxChildH = 0;
			Iterator<String> iter = children.keySet().iterator();
			while (iter.hasNext()) {
				String key = iter.next();
				maxChildW = Math.max(maxChildW,
						children.get(key).getPreferredSize().width);
				maxChildH = Math.max(maxChildH,
						children.get(key).getPreferredSize().height);
			}
			w += maxChildW;
			h += maxChildH;
			preferredSize = new Dimension(w, h);
			if (getBorder() != null) {
				getBorder().setPreferredSize(w, h);
			}
		}
		return preferredSize;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void handleMouseClick(final MouseEvent e, final float x,
			final float y) {
		Iterator<String> iter = children.keySet().iterator();
		while (iter.hasNext()) {
			GuiComponent child = children.get(iter.next());
			if (child.isVisible()
					&& child.contains(x, y)) {
				if (child instanceof Panel) {
					((Panel) child).handleMouseClick(e, x, y);
				} else if (child instanceof MenuGroup
						&& ((MenuGroup) child).isInHotSpot(x, y)) {
					GuiSelectable selected =
							((MenuGroup) child).getHighlighted();
					if (selected != null) {
						selected.onSelect();
					}
				} else if (child instanceof GuiSelectable
						&& ((GuiSelectable) child).isInHotSpot(x, y)) {
					((GuiSelectable) child).onSelect();
				}
				break;
			}
		}
	}
	/**
	 * Determines if the {@link CardPanel} is displaying a card.
	 * @return true if a child is visible; false otherwise
	 */
	public final boolean isShowingCard() {
		boolean showing = false;
		Iterator<String> iter = children.keySet().iterator();
		while (iter.hasNext()) {
			if (children.get(iter.next()).isVisible()) {
				showing = true;
				break;
			}
		}
		return showing;
	}
	/**
	 * {@inheritDoc}
	 */
	public final void move() {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	/*
	 * @Override public void prepareForRendering() throws Exception {
	 * ((GuiComponentImpl) this).prepareForRendering(); if (super.isVisible() &&
	 * super.getPosition() != null) { Iterator<String> iter =
	 * children.keySet().iterator(); while (iter.hasNext()) { GuiComponent c =
	 * children.get(iter.next()); if (c.isVisible() && c.getPosition() != null)
	 * { c.prepareForRendering(); break; } } } }
	 */
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final void setPosition(final double x, final double y,
			final double z) {
		super.setPosition(x, y, z);
		int innerW = preferredSize.width, innerH = preferredSize.height;
		// position all children
		double childX = x, childY = y, childZ = z + 20;
		if (super.getBorder() != null) {
			super.getBorder().setPosition(x, y, z);
			childX += getBorder().getInsets().left; // move right
			childY += getBorder().getInsets().bottom; // move up from bottom
			innerW -= getBorder().getInsets().left;
			innerW -= getBorder().getInsets().right;
			innerH -= getBorder().getInsets().top;
			innerH -= getBorder().getInsets().bottom;
		}
		// subtract insets
		childX += getInsets().left; // move right
		childY += getInsets().bottom; // move up
		innerW -= getInsets().left;
		innerW -= getInsets().right;
		innerH -= getInsets().top;
		innerH -= getInsets().bottom;
		// x and y should now be at bottom-left corner of inner area
		Iterator<String> iter = children.keySet().iterator();
		while (iter.hasNext()) {
			float offX = 0f, offY = 0f;
			GuiComponent child = children.get(iter.next());
			switch (super.getHorizontalAlignment()) {
			case GuiComponent.CENTER:
				offX += (innerW - child.getPreferredSize().width) / 2;
				break;
			case GuiComponent.RIGHT:
				offX += innerW - child.getPreferredSize().width;
				break;
			default: // LEFT
				break;
			}
			switch (super.getVerticalAlignment()) {
			case GuiComponent.TOP:
				offY += innerH - child.getPreferredSize().height;
				break;
			case GuiComponent.CENTER:
				offY += (innerH - child.getPreferredSize().height) / 2;
				break;
			default: // BOTTOM
				break;
			}
			child.setPosition(childX + offX, childY + offY, childZ);
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setPreferredSize(final int width, final int height) {
		preferredSize.width = width;
		preferredSize.width = height;
		if (super.getBorder() != null) {
			super.getBorder().setPreferredSize(width, height);
		}
	}
}
